package com.young.ysepay.service.impl;

import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.Producer;
import com.young.ysepay.beans.YsPayOrderBean;
import com.young.ysepay.connector.FileFegin;
import com.young.ysepay.connector.SysconfigFeign;
import com.young.ysepay.domain.YsReportReceiptDO;
import com.young.ysepay.dto.YsPayDTO;

import com.young.ysepay.mq.YsReturnMQConfig;
import com.young.ysepay.service.*;
import com.young.ysepay.utils.*;
import com.young.ysepay.utils.apiresult.ApiResultCode;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @anthor wenguoqiang
 * @date: 2019/06/06 10:13
 * @company 够样
 * @des
 **/
@Service
public class YsReportServiceImpl implements YsReportService {

    private static Logger log = LoggerFactory.getLogger(YsReportServiceImpl.class);


    @Autowired
    private YsBusinessPramService ysBusinessPramService;

    @Autowired
    private YsService ysService;

    @Autowired
    private SysconfigFeign sysconfigFeign;

    @Autowired
    private HttpClientUtils httpClientUtils;

    @Autowired
    private YsVerifyJsonSignService ysVerifyJsonSignService;

    @Autowired(required = false)
    private Producer producer;

    @Autowired
    private FileFegin fileFegin;

    @Autowired
    private YsReportReceiptService ysReportReceiptService;

    @Override
    public Map<String, Object> registryStore(Map<String, Object> params) {
        String user_status = null;
        Map<String, String> returnResult = new HashMap<>();
        YsReportReceiptDO ysReportReceiptDO = new YsReportReceiptDO();
        String merchant_no = params.get("mer_outside_custid").toString();
        try {
            YsPayDTO ysPayDTO = ysBusinessPramService.ysBusinessPram();
            //1.上传文件到银盛
            Map<String, Object> fileMap = JSONUtils.jsonToMap(params.get("fileMap").toString());
            Map<String, Object> tokenMap = ysService.yseUpToken();
            log.error("文件上传token获取{}", JSONUtils.beanToJson(tokenMap));

            boolean verifyResult = (boolean) tokenMap.get("verifyResult");


            returnResult.put("merchant_no", params.get("mer_outside_custid").toString());
            if (!verifyResult) {
                log.error("报备所需口令校验失败");
                return ReturnUtils.createReturnResult(ApiResultCode.OPRFAILURE.code(), "报备所需口令获取失败", false, JSONUtils.beanToJson(returnResult));
            }
            String token_status = (String) tokenMap.get("token_status");
            if (!"TOKEN_GET_SUCCESS".equals(token_status)) {
                log.error("报备所需口令校验失败");
                return ReturnUtils.createReturnResult(ApiResultCode.OPRFAILURE.code(), "报备所需口令获取失败", false, JSONUtils.beanToJson(returnResult));
            }

            String token = tokenMap.get("token").toString();
            if (StringUtils.isEmpty(token)) {
                log.error("报备所需口令获取为空");
                return ReturnUtils.createReturnResult(ApiResultCode.OPRFAILURE.code(), "报备所需口令获取失败", false, JSONUtils.beanToJson(returnResult));
            }
            //上传银盛文件
            Map<String, String> uploadErrorResult = this.uploadYSReportfile(fileMap, token);

            if (uploadErrorResult != null && !(uploadErrorResult.isEmpty())) {
                //失败
                String error = uploadErrorResult.get("error");
                if (StringUtils.isNotBlank(error)) {
                    StringBuilder message = new StringBuilder(error);
                    Set<Map.Entry<String, String>> errorEntrySet = uploadErrorResult.entrySet();
                    for (Map.Entry<String, String> entry : errorEntrySet) {
                        //图片类型
                        message.append(String.format("%s:%s", imageTypeUtils.ImageTypeMap.get(entry.getKey()) ,entry.getValue()));
                    }
                    returnResult.put("msg", message.toString());
                    return ReturnUtils.createReturnResult(ApiResultCode.OPRFAILURE.code(), error, false, JSONUtils.beanToJson(returnResult));
                }
            }


            // 对以上信息组装为银盛参数
            YsPayOrderBean ysPayOrderBean = new YsPayOrderBean();
            ysPayOrderBean.setCust_name(params.get("cust_name").toString());
            ysPayOrderBean.setCust_type(params.get("cust_type").toString());
            //非小微商户设置
            if (!Boolean.valueOf(params.get("isXW").toString())) {
                ysPayOrderBean.setLegal_name(params.get("legal_name").toString());
                ysPayOrderBean.setBus_license(params.get("bus_license").toString());
                ysPayOrderBean.setBus_license_expire(params.get("bus_license_expire").toString());
            }
            //去除详细地址中的特殊符号
            String company_addr = YsStringUtils.StringFilter(params.get("company_addr").toString());
            ysPayOrderBean.setAnother_name(params.get("another_name").toString());
            ysPayOrderBean.setLegal_tel(params.get("legal_tel").toString());
            ysPayOrderBean.setLegal_cert_type(params.get("legal_cert_type").toString());
            ysPayOrderBean.setLegal_cert_no(params.get("legal_cert_no").toString());
            ysPayOrderBean.setLegal_cert_no_time(params.get("legal_cert_no_time").toString());
            ysPayOrderBean.setProvince(params.get("province").toString());
            ysPayOrderBean.setCity(params.get("city").toString());
            ysPayOrderBean.setCompany_addr(company_addr);
            ysPayOrderBean.setIndustry(params.get("industry").toString());
            ysPayOrderBean.setSettle_type(params.get("settle_type").toString());
            ysPayOrderBean.setBank_account_no(params.get("bank_account_no").toString());
            ysPayOrderBean.setBank_account_name(params.get("bank_account_name").toString());
            ysPayOrderBean.setBank_account_type(params.get("bank_account_type").toString());
            ysPayOrderBean.setBank_name(params.get("bank_name").toString());
            ysPayOrderBean.setBank_type(params.get("bank_type").toString());
            ysPayOrderBean.setBank_province(params.get("bank_province").toString());
            ysPayOrderBean.setBank_city(params.get("bank_city").toString());
            ysPayOrderBean.setBank_card_type(params.get("bank_card_type").toString());
            ysPayOrderBean.setCert_no(params.get("cert_no").toString());
            ysPayOrderBean.setCert_type(params.get("cert_type").toString());
            ysPayOrderBean.setBank_telephone_no(params.get("bank_telephone_no").toString());
            ysPayOrderBean.setMer_outside_custid(merchant_no);
            ysPayOrderBean.setToken(token);
            //需要注意是子机构号还是主机构号
            ysPayOrderBean.setOrg_no(ysPayDTO.getORG_NO());

            log.error("银盛报备未签名参数：{}",ysPayOrderBean);

            Map<String, Object> registStore = null;

            registStore = ysService.ysRegistStore(ysPayOrderBean);


            boolean registResult = (boolean) registStore.get("verifyResult");
            if (!registResult) {
                return ReturnUtils.createReturnResult(ApiResultCode.OPRFAILURE.code(), "报备失败", false, JSONUtils.beanToJson(returnResult));
            }

            String code = registStore.get("code").toString();
            //根据平台商唯一标识查询是否存在记录，有则修改，无则save操作
            YsReportReceiptDO ysReportReceipt = ysReportReceiptService.get(ysPayOrderBean.getMer_outside_custid());
            //根據返回的状态进行判断
            if (!("10000").equals(code)) {
                //String subCode = registStore.get("sub_code").toString();
                String subMsg = registStore.get("sub_msg").toString();
                returnResult.put("msg", subMsg);
                if (null == ysReportReceipt || ysReportReceipt.equals("")) {
                    // 保存同步回执信息
                    ysReportReceiptDO.setId(ysPayOrderBean.getMer_outside_custid());
                    ysReportReceiptDO.setReportReceiptMsg(subMsg);
                    ysReportReceiptDO.setReportReceiptCreate(new Date());
                    ysReportReceiptDO.setReportReceiptModified(new Date());
                    ysReportReceiptDO.setIsDelete("1");
                    ysReportReceiptDO.setReportReceiptCode("9999");
                    ysReportReceiptService.save(ysReportReceiptDO);
                    log.error("报备失败记录" + ysReportReceiptDO.toString());
                }
                return ReturnUtils.createReturnResult(ApiResultCode.OPRFAILURE.code(), StringUtils.isBlank(subMsg) ? "报备失败" : subMsg, false, JSONUtils.beanToJson(returnResult));
            }
            user_status = registStore.get("user_status").toString();
            String usercode = registStore.get("usercode").toString();


            returnResult.put("userStatus", user_status);
            returnResult.put("usercode", usercode);

            if (user_status.equals("生效")) {
                log.error("报备同步返回成功信息{}" , JSONUtils.objectToJson(returnResult));
                return ReturnUtils.createReturnResult(ApiResultCode.OPRSUCCESS.code(), "报备成功", true, JSONUtils.beanToJson(returnResult));
            } else {
                log.error("报备同步返回失败信息{}" ,JSONUtils.objectToJson(returnResult));
                return ReturnUtils.createReturnResult(ApiResultCode.OPRFAILURE.code(), user_status, false, JSONUtils.beanToJson(returnResult));
            }

        } catch (Exception e) {
            //通知商户中心异常处理
            /*Map errorResult = new HashMap();
            errorResult.put("merchant_no",merchant_no);
            errorResult.put("msg",e.getMessage());
            Message message = new Message(YsReturnMQConfig.STORE_TOPIC, YsReturnMQConfig.YSREQUERTERRORRESULT, JSONUtils.objectToJson(errorResult).getBytes());
            producer.send(message);*/

            //将完整堆栈报错日志信息输出 getMessage 等相关的输出不够完整
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            PrintStream pout = new PrintStream(out);
            e.printStackTrace(pout);
            String ret = new String(out.toByteArray());
            pout.close();
            try {
                out.close();
            } catch (Exception ex) {

            }
            log.error("报备异常：{}",ret);
            e.printStackTrace();
            return ReturnUtils.createReturnResult(ApiResultCode.OPRFAILURE.code(), user_status, false, JSONUtils.beanToJson(returnResult));

        }

    }

    @Override
    public void notifyRegistry(Map<String, String[]> requestParams) {

        StringBuilder sb = new StringBuilder();
        sb.append("\r\n 银盛报备异步回调开始 ");
        Map<String, String> params = new HashMap<String, String>();

        for (Map.Entry<String, String[]> entry : requestParams.entrySet()) {
            String name = entry.getKey();
            String[] values = entry.getValue();
            StringBuffer valueStr = null;

            if (values != null) {
                valueStr = new StringBuffer();
                for (int i = 0; i < values.length; i++) {
                    valueStr = (i == values.length - 1) ? valueStr.append(values[i]) : valueStr.append(values[i]).append(",");
                }
                params.put(name, valueStr.toString());
            }

        }
        sb.append("==========resString=============" + params.toString());
        try {

            boolean verifyResult = ysVerifyJsonSignService.verifySign(params);
            System.out.println(verifyResult);
            // 状态
            if (verifyResult) { // 验证成功
                System.out.println("异步通知验证签名成功");
                sb.append("异步通知验证签名成功");
                //获取异步回执信息状态码
                //String code = params.get("code");

                //获取平台商唯一标识
                String merchant_no = params.get("merchant_no");
                //根据平台商唯一标识查询是否有该条记录，如果有进行update操作 如果没有进行save操作
                YsReportReceiptDO ysReportReceiptDO = ysReportReceiptService.get(merchant_no);
                //
                YsReportReceiptDO ysReportReceipt = new YsReportReceiptDO();
                String cust_statue = params.get("cust_statue");
                String note = params.get("note");
                String user_status = params.get("user_status");
                String custname = params.get("custname");
                String usercode = params.get("usercode");
                String custid = params.get("custid");
                if (cust_statue.equals("生效")) {
                    ysReportReceipt.setReportReceiptCode("10000");
                } else {
                    ysReportReceipt.setReportReceiptCode("9999");
                }
                if (ysReportReceiptDO == null || ysReportReceiptDO.equals("")) {
                    //保存
                    ysReportReceipt.setReportReceiptMsg(note);
                    ysReportReceipt.setReportReceiptCuststate(cust_statue);
                    ysReportReceipt.setReportReceiptUsercode(usercode);
                    ysReportReceipt.setId(merchant_no);
                    ysReportReceipt.setReportReceiptCreate(new Date());
                    ysReportReceipt.setIsDelete("1");
                    ysReportReceipt.setReportReceiptUserstatus(user_status);
                    ysReportReceipt.setReportReceiptCustname(custname);
                    ysReportReceipt.setReportReceiptCustid(custid);
                    ysReportReceiptService.save(ysReportReceipt);
                    log.error("保存数据" + ysReportReceipt.toString());
                } else {
                    ysReportReceipt.setReportReceiptMsg(note);
                    ysReportReceipt.setReportReceiptCuststate(cust_statue);
                    ysReportReceipt.setReportReceiptUsercode(usercode);
                    ysReportReceipt.setId(merchant_no);
                    ysReportReceipt.setReportReceiptModified(new Date());
                    ysReportReceipt.setIsDelete("1");
                    ysReportReceipt.setReportReceiptUserstatus(user_status);
                    ysReportReceipt.setReportReceiptCustname(custname);
                    ysReportReceipt.setReportReceiptCustid(custid);
                    ysReportReceipt.setReportReceiptCode("9999");
                    ysReportReceiptService.update(ysReportReceipt);
                    log.error("修改数据" + ysReportReceipt.toString());
                }
                Message message = new Message(YsReturnMQConfig.STORE_TOPIC, YsReturnMQConfig.YSREPORT, JSONUtils.objectToJson(params).getBytes());
                producer.send(message);


            } else {// 验证失败
                sb.append("异步通知验证签名失败");
                log.error("异步通知验证签名失败" + sb.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            log.error(sb.toString());
        }
    }

    @Override
    public Map<String, Object> requertRegistryStore(Map<String, Object> mapParams) {

        Message message = new Message(YsReturnMQConfig.YS_TOPIC, YsReturnMQConfig.YSREQUERTREPORT, JSONUtils.objectToJson(mapParams).getBytes());
        producer.send(message);
        return ReturnUtils.createReturnResult(ApiResultCode.OPRSUCCESS.code(), "报备请求成功", true, "");
    }

    private String download(String fileUuid, String fileName, String randomStr) {
        String returnPath = "";
        //Response response = fileFegin.rpcDownLoadFile(fileUuid);
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            inputStream = httpClientUtils.HttpGetDownLoad(fileFegin.getDownloadUrl(fileUuid));
            //缺省地址
            String path = "/tmp/tempfile/ysUp/" + randomStr + "/";

            //以商户为目录避免文件覆盖
            File file = new File(path);
            if (!file.exists()) {
                file.mkdirs();
            }
            returnPath = path + fileName;
            //100kb
            byte[] bs = new byte[102400];
            int length = 0;
            outputStream = new FileOutputStream(returnPath);
            // 开始读取
            while ((length = inputStream.read(bs)) != -1) {
                outputStream.write(bs, 0, length);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                // 完毕，关闭所有链接
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
        return returnPath;
    }


    public Map<String, String> uploadYSReportfile(Map<String, Object> map, String token) {


        YsPayDTO ysPayDTO = ysBusinessPramService.ysBusinessPram();


        Map<String, String> returnMap = new HashMap<>();
        if (map != null && map.size() > 0) {
            Set<Map.Entry<String, Object>> entrySet = map.entrySet();
            for (Map.Entry<String, Object> entry : entrySet) {
                String type = entry.getKey();
                String value = entry.getValue().toString();

                File file = new File(download(value, type + ".jpg", sysconfigFeign.getUuidByLeaf()));
                try {
                    Map<String, String> param = new HashMap<String, String>();
                    param.put("picType", type);
                    param.put("token", token);
                    param.put("superUsercode", ysPayDTO.getPARTNER_ID());
                    String resMessage = httpClientUtils.doPostUpload(ysPayDTO.getYSEPAY_IMAGE_UP_URL(), param, "param3", file);
                    Map<String, Object> mapPrarmsFromJson = JSONUtils.jsonToMap(resMessage);
                    boolean flag = (boolean) mapPrarmsFromJson.get("isSuccess");
                    if (!flag) {
                        String message = (String) mapPrarmsFromJson.get("errorMsg");
                        returnMap.put(type, message);
                    }
                    System.out.println(String.format("类型: %s 上传返回信息：%s", param.get("picType"), resMessage));
                    log.info(String.format("类型: %s 上传返回信息：%s", param.get("picType"), resMessage));
                } catch (Exception e) {
                    e.printStackTrace();
                    returnMap.put("error", "上传失败");
                    log.info("上传文件出现问题");
                } finally {
                    //清除临时文件
                    this.deleteFile(file);
                }
            }
        }
        return returnMap;
    }

    public static void deleteFile(File file) {
        if ((file.exists()) && (!file.isDirectory()))
            file.delete();
    }


}
